package Infix2RPM.processor.infixElement;

import Infix2RPM.processor.Exception.BasicOperandException;
import Infix2RPM.processor.Exception.BasicOperatorException;
import Infix2RPM.processor.Exception.LogicException;
import Infix2RPM.processor.Stack.BasicOperand;

public class DoubleOperand implements BasicOperand {
	private Double value = null;

	public DoubleOperand(Double value) {
		this.value = value;
	}

	public DoubleOperand add(BasicOperand operand) throws LogicException {
		if (!(operand.getValue() instanceof Double)) {
			toss("Operand to add is not a Double");
		}
		return new DoubleOperand(this.value += (Double) operand.getValue());
	}

	public DoubleOperand subtract(BasicOperand operand) throws LogicException {
		if (!(operand.getValue() instanceof Double)) {
			toss("Operand to subtract is not a Double");
		}
		return new DoubleOperand(this.value -= (Double) operand.getValue());
	}

	public DoubleOperand divide(BasicOperand operand) throws LogicException {
		if (!(operand.getValue() instanceof Double)) {
			toss("Operand to divide is not a Double");
		}
		return new DoubleOperand(this.value /= (Double) operand.getValue());
	}

	public DoubleOperand multiply(BasicOperand operand) throws LogicException {
		if (!(operand.getValue() instanceof Double)) {
			toss("Operand to multiply is not a Double");
		}
		return new DoubleOperand(this.value *= (Double) operand.getValue());
	}

	public DoubleOperand power(BasicOperand operand) throws LogicException {
		if (!(operand.getValue() instanceof Integer)) {
			toss("Operand to power is a Double");
		}
		return new DoubleOperand(this.value = Math.pow(value.doubleValue(),
				((Double) operand.getValue()).doubleValue()));
	}

	public DoubleOperand mod(BasicOperand operand) throws LogicException {
		if (!(operand.getValue() instanceof Double)) {
			toss("Operand to divide is not a Double");
		}
		return new DoubleOperand(this.value.doubleValue() % ((Double) operand.getValue()).doubleValue());
	}

	public BasicOperand concat(BasicOperand operand) throws LogicException {
		throw new BasicOperatorException(
				"Concatentation of Doubles is unsupported", this.className());
	}

	public BooleanOperand equal(BasicOperand operand) throws LogicException {
		if (!(operand.getValue() instanceof Double)) {
			toss("Operand to == is not a Double");
		}
		return new BooleanOperand(this.value.doubleValue() == ((Double) operand.getValue())
				.doubleValue());
	}

	public BooleanOperand lessThan(BasicOperand operand) throws LogicException {
		if (!(operand.getValue() instanceof Double)) {
			toss("Operand to < is not a Double");
		}
		return new BooleanOperand(
				value.doubleValue() < ((Double) operand.getValue())
						.doubleValue());
	}

	public BooleanOperand lessThanEqual(BasicOperand operand)
			throws LogicException {
		if (!(operand.getValue() instanceof Double)) {
			toss("Operand to <= is not a Double");
		}
		return new BooleanOperand(
				this.value <= ((Double) operand.getValue()).doubleValue());
	}

	public BooleanOperand greaterThan(BasicOperand operand)
			throws LogicException {
		if (!(operand.getValue() instanceof Double)) {
			toss("Operand to > is not a Double");
		}
		return new BooleanOperand(
				this.value > ((Double) operand.getValue()).doubleValue());
	}

	public BooleanOperand greaterThanEqual(BasicOperand operand)
			throws LogicException {
		if (!(operand.getValue() instanceof Double)) {
			toss("Operand to >= is not a Double");
		}
		return new BooleanOperand(
				this.value >= ((Double) operand.getValue()).doubleValue());
	}

	public BooleanOperand or(BasicOperand operand) throws LogicException {
		throw new BasicOperatorException(
				"Logical OR using Double is unsupported", this.className());
	}

	public BooleanOperand and(BasicOperand operand) throws LogicException {
		throw new BasicOperatorException(
				"logical AND using Double is unsupported", this.className());
	}

	public boolean isNull() {
		return this.value == null;
	}

	public boolean isEmpty() {
		return this.value == null;
	}

	public Object getValue() {
		return this.value;
	}

	private void toss(String message) throws LogicException {
		throw new BasicOperandException(message, this.getClass().getName());
	}

	public String getValueAsString() {
		return this.value.toString();
	}
	
	public boolean isEqual(String token) {
		return this.value.toString().equals(token);
	}

	private String className() {
		return this.getClass().getName();
	}
}
